package com.hsylient.javase.chapter14;

import lombok.SneakyThrows;
import org.junit.Test;

import javax.crypto.Cipher;
import java.security.*;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class RSAUtil {
    //生成秘钥对
    public static KeyPair getKeyPair() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        return keyPair;
    }

//    //获取公钥(Base64编码)
//    public static String getPublicKey(KeyPair keyPair) {
//        PublicKey publicKey = keyPair.getPublic();
//        byte[] bytes = publicKey.getEncoded();
//        return byte2Base64(bytes);
//    }
//
//    //获取私钥(Base64编码)
//    public static String getPrivateKey(KeyPair keyPair) {
//        PrivateKey privateKey = keyPair.getPrivate();
//        byte[] bytes = privateKey.getEncoded();
//        return byte2Base64(bytes);
//    }
//
//    //将Base64编码后的公钥转换成PublicKey对象
//    public static PublicKey string2PublicKey(String pubStr) throws Exception {
//        byte[] keyBytes = base642Byte(pubStr);
//        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
//        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
//        PublicKey publicKey = keyFactory.generatePublic(keySpec);
//        return publicKey;
//    }
//
//    //将Base64编码后的私钥转换成PrivateKey对象
//    public static PrivateKey string2PrivateKey(String priStr) throws Exception {
//        byte[] keyBytes = base642Byte(priStr);
//        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
//        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
//        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
//        return privateKey;
//    }
//
//    //公钥加密
//    public static byte[] publicEncrypt(byte[] content, PublicKey publicKey) throws Exception {
//        Cipher cipher = Cipher.getInstance("RSA");
//        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
//        byte[] bytes = cipher.doFinal(content);
//        return bytes;
//    }
//
//    //私钥解密
//    public static byte[] privateDecrypt(byte[] content, PrivateKey privateKey) throws Exception {
//        Cipher cipher = Cipher.getInstance("RSA");
//        cipher.init(Cipher.DECRYPT_MODE, privateKey);
//        byte[] bytes = cipher.doFinal(content);
//        return bytes;
//    }
//
//    //字节数组转Base64编码
//    public static String byte2Base64(byte[] bytes) {
//        BASE64Encoder encoder = new BASE64Encoder();
//        return encoder.encode(bytes);
//    }
//
//    //Base64编码转字节数组
//    public static byte[] base642Byte(String base64Key) throws IOException {
//        BASE64Decoder decoder = new BASE64Decoder();
//        return decoder.decodeBuffer(base64Key);
//    }

    @SneakyThrows
    public static void main(String[] args) {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        PrivateKey privateKey = keyPair.getPrivate();
        byte[] encoded = privateKey.getEncoded();
        System.out.println("私钥：" + Base64.getEncoder().encodeToString(encoded));

        PublicKey publicKey = keyPair.getPublic();
        byte[] encoded1 = publicKey.getEncoded();
        System.out.println("公钥：" + Base64.getEncoder().encodeToString(encoded1));

        String helloWord = "HelloWord";

        // 公钥加密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        byte[] bytes = cipher.doFinal(helloWord.getBytes());

        // 私钥解密
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        System.out.println(new String(cipher.doFinal(bytes)));

//        Map<String, String> privatePublic = getPrivatePublic();
//        System.out.println(privatePublic);
    }


    /**
     * 获取秘钥对
     *
     * @return 秘钥对
     */
    @SneakyThrows
    public static Map<String, String> getPrivatePublicString() {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        PrivateKey privateKey = keyPair.getPrivate();
        byte[] encoded = privateKey.getEncoded();
        Map<String, String> map = new HashMap<>(2);
        map.put("私钥", Base64.getEncoder().encodeToString(encoded));
        PublicKey publicKey = keyPair.getPublic();
        byte[] publicKeyEncoded = publicKey.getEncoded();
        map.put("公钥", Base64.getEncoder().encodeToString(publicKeyEncoded));
        return map;
    }

    @SneakyThrows
    public static Map<String, Key> getPrivatePublic() {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();
        Map<String, Key> map = new HashMap<>(2);
        map.put("私钥", privateKey);
        map.put("公钥", publicKey);
        return map;
    }

    // 公钥加密
    @SneakyThrows
    public String publicEn(String content, PublicKey publicKey) {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] bytes = cipher.doFinal(content.getBytes());
        return Base64.getEncoder().encodeToString(bytes);
    }

    // 私钥解密
    @SneakyThrows
    public String privateDe(String content, PrivateKey privateKey) {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] bytes = cipher.doFinal(Base64.getDecoder().decode(content));
        return new String(bytes);
    }

    @Test
    public void testPublicPrivate() {
        String content = "HelloWord";
        Map<String, Key> privatePublic = getPrivatePublic();
        String mimi = publicEn(content, (PublicKey) privatePublic.get("公钥"));
        String target = privateDe(mimi, (PrivateKey) privatePublic.get("私钥"));
        System.out.println(target);
    }
}